﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
namespace MapSurface.UIModelElement
{
    public class UIElement
    {
        #region Properties
        private string _name;

        private Object _xalmObject;

        public Object XalmObject
        {
            get { return _xalmObject; }
            set { _xalmObject = value; }
        }

        private XmlNode _xamlNode;

        public XmlNode XamlNode
        {
            get { return _xamlNode; }
            set { _xamlNode = value; }
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private int _id=-1;

        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }
        private Widget _widgetType;

        public Widget WidgetType
        {
            get { return _widgetType; }
            set { _widgetType = value; }
        }
        private List<Property> _properties;

        public List<Property> Properties
        {
            get { return _properties; }
            set { _properties = value; }
        }
        private List<Event> _events;

        public List<Event> Events
        {
            get {
                if (_events != null && _events.Count > 0 && _events[0].Name.CompareTo("ValueChanged") == 0)
                    Console.Out.Write("");
                return _events; }
            set { _events = value; }
        }

         #endregion

        #region Constructors
        public UIElement(XmlNode current)
        {
            this._xamlNode = current;
            if(current.Attributes.GetNamedItem("name")!=null)
                this._name = current.Attributes.GetNamedItem("name").Value;
            if(current.Attributes.GetNamedItem("id")!=null)
                this._id = int.Parse(current.Attributes.GetNamedItem("id").Value);
            if(current.HasChildNodes)
            foreach (XmlNode n in current.ChildNodes){
                if (n.Name.CompareTo("widgetType") == 0)
                    this._widgetType = new Widget(n);
                else if (n.Name.CompareTo("properties") == 0)
                {
                    if (this._properties == null)
                        this._properties = new List<Property>();
                    this._properties.Add(new Property(n));

                }
                else if(n.Name.CompareTo("events") == 0)
                {
                    if (this._events == null)
                        this._events = new List<Event>();
                      this._events.Add(new Event(n));

                }

            }
           
        }

        public UIElement(XmlNode currentType, int id, string name)
        {
            this._xamlNode = currentType;
            this._name = name;
            this._id = id;
            if (currentType.HasChildNodes)
                foreach (XmlNode n in currentType.ChildNodes)
                {
                    if (n.Name.CompareTo("widgetType") == 0)
                        this._widgetType = new Widget(n);
                    else if (n.Name.CompareTo("properties") == 0)
                    {
                        if (this._properties == null)
                            this._properties = new List<Property>();
                        this._properties.Add(new Property(n));

                    }
                    else if (n.Name.CompareTo("events") == 0)
                    {
                        if (this._events == null)
                            this._events = new List<Event>();
                        this._events.Add(new Event(n));

                    }

                }

        }
        public UIElement( )
        {
        }

        #endregion

        public List<Behaviour> getBehaviour()
        {
            return this.WidgetType.getBehaviour();
        }
        public Property getContentProperty()
        {
            if(Properties!=null)
            foreach (Property prop in Properties)
            {
                if (prop.isRenderingProperty())
                    return prop;
            }
            return null;
        }
        public string toString(string space)
        {
            string ret = "";
            if (Id != -1)
                ret += (space + "<containsUIElement  name='" + Name + "' id='" + Id + "'>\n");
            else
                ret += (space + "<containsUIElement  name='" + Name + "' >\n");
            if (this.Events != null && this.Events.Count > 0)
                foreach (Event e in this.Events)
                    ret += (space + "\t" + e.toString(1, space + " "));
            if (this.Properties != null && this.Properties.Count > 0)
                foreach (Property p in this.Properties)
                    ret += (space + "\t" + p.toString(space + " "));
            ret += (space + this.WidgetType.toString(space + " ") );
            ret += (space + "</containsUIElement>\n");
            return ret;
        }
    }
    public class Container:UIElement
    {
        public  enum _layout {top=1,left,bottom,right,none,absolute};

        private bool _isRoot = false;

        public bool IsRoot
        {
            get { return _isRoot; }
            set { _isRoot = value; }
        }
        private List<UIElement> _contains;

        public List<UIElement> Contains
        {
            get { return _contains; }
            set { _contains = value; }
        }
        public Property getContentProperty()
        {
            if(Properties!=null)
            foreach (Property prop in Properties)
            {
                if (prop.isRenderingProperty())
                    return prop;
            }
            return null;
        }

        public Container(XmlNode current)
        {
            if (current == null)
                Console.Out.WriteLine();
            this.XalmObject = current;
            this.XamlNode = current;
            this.Name = current.Attributes.GetNamedItem("name").Value;
            if (current.Attributes.GetNamedItem("Id") != null)
                this.Id = int.Parse(current.Attributes.GetNamedItem("Id").Value);
            if (current.HasChildNodes)
                foreach (XmlNode n in current.ChildNodes)
                {
                    if (n.Name.CompareTo("widgetType") == 0)
                        this.WidgetType = new Widget(n);
                    else if (n.Name.CompareTo("properties") == 0)
                    {
                        if (this.Properties == null)
                            this.Properties = new List<Property>();
                        this.Properties.Add(new Property(n));

                    }
                    else if (n.Name.CompareTo("events") == 0)
                    {
                        if (this.Events == null)
                            this.Events = new List<Event>();
                        this.Events.Add(new Event(n));

                    }
                    else if (n.Name.CompareTo("containsUIElement") == 0)
                    {
                        if(this.Contains==null)
                            this.Contains = new List<UIElement>();
                        if (n.Attributes.GetNamedItem("xsi:type") != null)
                        {
                            Container c = new Container(n);
                            this.Contains.Add(c);
                        }
                        else
                            this.Contains.Add(new UIElement(n));
                    }

                }
  
        }
        public Container(XmlNode currentType, int id, string name, List<UIElement> child)
        {
            this.XalmObject = currentType;
            this.XamlNode = currentType;
            this.Name = name;
            this.Id = id;
            if (currentType.HasChildNodes)
                foreach (XmlNode n in currentType.ChildNodes)
                {
                    if (n.Name.CompareTo("widgetType") == 0)
                        this.WidgetType = new Widget(n);
                    else if (n.Name.CompareTo("properties") == 0)
                    {
                        if (this.Properties == null)
                            this.Properties = new List<Property>();
                        this.Properties.Add(new Property(n));

                    }
                    else if (n.Name.CompareTo("events") == 0)
                    {
                        if (this.Events == null)
                            this.Events = new List<Event>();
                        this.Events.Add(new Event(n));

                    }
                    else if (n.Name.CompareTo("containsUIElement") == 0)
                    {
                        this.Contains = new List<UIElement>();
                        if (n.Attributes.GetNamedItem("xsi:type") != null)
                        {
                            Container c = new Container(n);
                            this.Contains.Add(c);
                        }
                        else
                            this.Contains.Add(new UIElement(n));
                    }


                }
            this.Contains = child;

        }
        public string toString(bool root, string space)
        {
            string ret = "";
            if (root)
                ret += (space + "<contains xsi:type='UIModel:Container' name='" + base.Name + "'>\n");
            else
                if (Id != -1)
                    ret += (space + "<containsUIElement xsi:type='UIModel:Container' name='" + base.Name + "' id='" + base.Id + "'>\n");
                else
                    ret += (space + "<containsUIElement xsi:type='UIModel:Container' name='" + base.Name + "' >\n");
            if (this.Events != null && this.Events.Count > 0)
                foreach (Event e in this.Events)
                    ret += (space +"\t"+ e.toString(1, space + " ") );
            if (this.Properties != null && this.Properties.Count > 0)
                foreach (Property p in this.Properties)
                    ret += (space + "\t" + p.toString(space + " "));
            ret += (space + "\t" + this.WidgetType.toString(space + " "));
            if (_contains != null && _contains.Count > 0)
                foreach (UIElement e in _contains)
                    try
                    {
                        ret += (space + "\t" + ((Container)e).toString(false, space + " "));
                    }
                    catch (InvalidCastException)
                    {
                        ret += (space + "\t" + e.toString(space + " "));
                    }
            if (root)
                ret += (space + "</contains>\n");
            else
                ret += (space + "</containsUIElement>\n");

            return ret;
        }
    }
    public class Property
    {
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private string _value;

        public string Value
        {
            get { return _value; }
            set { _value = value; }
        }
        private string _valueType=null;

        public string ValueType
        {
            get { return _valueType; }
            set { _valueType = value; }
        }

        private XmlNode _node;

        public XmlNode Node
        {
            get { return _node; }
            set { _node = value; }
        }
        private string renderingProperty = null;
        public bool isRenderingProperty()
        {
            return renderingProperty != null;
        }
        public Property(String name, String value, String dataType)
        {
            Name = name;
            Value = value;
            ValueType = dataType;
        }
        public Property(XmlNode node)
        {
            Name = node.Attributes.GetNamedItem("name").Value;
            if(node.Attributes.GetNamedItem("value")!=null)
                Value = node.Attributes.GetNamedItem("value").Value;
            if (node.Attributes.GetNamedItem("valueType") != null)
                ValueType = node.Attributes.GetNamedItem("valueType").Value;
            if (node.HasChildNodes)
                renderingProperty = "<renderingProperty/>";
            _node = node;
        }
        public string toString(string space)
        {
            string s = "";
            if (renderingProperty != null)
                if (_valueType != null)
                    s += (space + "<properties name='" + _name + "' dataType='" + _valueType + "' ><renderingProperty/></properties>\n");
                else
                    s += (space + "<properties name='" + _name + "' ><renderingProperty/></properties>\n");
            else
                if (_valueType != null)
                    s += (space + "<properties name='" + _name + "' dataType='" + _valueType + "' />\n");
                else
                    s += (space + "<properties name='" + _name + "'  />\n");
            return s ;
        }

    }
    public class Event
    {
        private string _name;
        private XmlNode _node;
        private String _mappedBehavior="";

        public XmlNode Node
        {
            get { return _node; }
            set { _node = value; }
        }


        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private List<string> _parameters;

        public List<string> Parameters
        {
            get { return _parameters; }
            set { _parameters = value; }
        }
        private string _scriptCode;

        public string ScriptCode
        {
            get { return _scriptCode; }
            set { _scriptCode = value; }
        }
        private List<Behaviour> _implementedBehavoir;

        public List<Behaviour> ImplementedBehavoir
        {
            get { return _implementedBehavoir; }
            set { _implementedBehavoir = value; }
        }
        private List<Property> _linkedProperties;

        public List<Property> LinkedProperties
        {
            get { return _linkedProperties; }
            set { _linkedProperties = value; }
        }
        public Event(String name, String scode, List<string> param)
        {
            Name = name;
            ScriptCode = scode;
            Parameters = param;
        }
        public Event(XmlNode node)
        {
            Name = node.Attributes.GetNamedItem("name").Value;
            if(node.Attributes.GetNamedItem("scriptCode")!=null)
                ScriptCode = node.Attributes.GetNamedItem("scriptCode").Value;
            if(node.HasChildNodes)
                foreach (XmlNode n in node.ChildNodes)
                {
                    if(ImplementedBehavoir==null)
                        ImplementedBehavoir = new List<Behaviour>();
                    ImplementedBehavoir.Add(new Behaviour(n));

                }
            _node = node;
        }
        public Event(XmlNode node,int i)
        {
            Name = node.Attributes.GetNamedItem("name").Value;
            ScriptCode = node.Attributes.GetNamedItem("scriptCode").Value;
            if (node.HasChildNodes)
                foreach (XmlNode n in node.ChildNodes)
                    _mappedBehavior += (n.OuterXml+"\n");
            _node = node;
        }
        public string toString(int i, string space)
        {
  
            string ret = "";
            if (i == 0)
            {

                ret += (space + "<events name='" + _name + "' >\n");
                if(ImplementedBehavoir!=null)
                    foreach (Behaviour b in ImplementedBehavoir)
                        ret += (space + "\t" + b.toString(space + " "));
                ret += (space + "</events>\n");
            }
            else
            {
                if(ScriptCode!=null)
                    ret +=( space + "<events name='" + _name + "' scriptCode='" + ScriptCode + "' >\n");
                else
                    ret +=( space + "<events name='" + _name + "'   >\n");
                if (ImplementedBehavoir != null)
                    foreach (Behaviour b in ImplementedBehavoir)
                        ret += (space + "\t" + b.toString(space + " "));
                ret += (space + "</events> \n");
            }
            return ret;
        }


    }
    public class Widget
    {
        private String _name;
        private string _id=null;
        private string _isContainer="false";
        private List<String> _cardinality;
        private List<Property> _properties = null;

        public List<Property> Properties
        {
            get { return _properties; }
            set { _properties = value; }
        }
        private List<Event> _events = null;

        public List<Event> Events
        {
            get { return _events; }
            set { _events = value; }
        }

        public List<Behaviour> getBehaviour()
        {
            List<Behaviour> lb = new List<Behaviour>();
            List<String> name = new List<string>();
            if (Events != null)
                foreach (Event e in Events)
                    if (e.ImplementedBehavoir != null)
                        foreach (Behaviour b in e.ImplementedBehavoir)
                        {
                            if (!name.Contains(b.XmlNode) && b.XmlNode.Contains("<mappedBehaviors"))
                            {
                                lb.Add(b);
                                name.Add(b.XmlNode);
                            }
                        }


            return lb;
        }
        public Property getContentProperty()
        {
            if (Properties != null)
                foreach (Property prop in Properties)
                {
                    if (prop.isRenderingProperty())
                        return prop;
                }
            return null;
        }


        public String Name
        {
            get {
                if (_name.Contains(":"))
                    return _name.Substring(2);
                return _name;
            }
            set { _name = value; }
        }
        private XmlNode _node;

        public XmlNode Node
        {
            get { return _node; }
            set { _node = value; }
        }
        private Widget containsWidgets;

        public Widget ContainsWidgets
        {
            get { return containsWidgets; }
            set { containsWidgets = value; }
        }
        public Widget(XmlNode node)
        {
            this._name = node.Attributes.GetNamedItem("name").Value;
            this._node = node;
            if(node.Attributes.GetNamedItem("id")!=null)
                this._id= node.Attributes.GetNamedItem("id").Value;
            if(node.Attributes.GetNamedItem("isContainer")!=null)
                this._isContainer=node.Attributes.GetNamedItem("isContainer").Value;
            this._cardinality = new List<string>();
            if(node.HasChildNodes)
                foreach (XmlNode n in node.ChildNodes)
                {
                    if (n.Name.CompareTo("containsWidget") == 0)
                    {
                        this.containsWidgets = new Widget(n);
                        
                    }
                    else if (   n.Name.CompareTo("cardinality") == 0)
                    {
                        _cardinality.Add(n.OuterXml);
                    }
                    else if (n.Name.CompareTo("properties") == 0)
                    {
                        Property p = new Property(n);
                        if(_properties==null)
                            _properties= new List<Property>();
                        this._properties.Add(p);
                    }
                    else if (n.Name.CompareTo("events") == 0)
                    {
                        Event e = new Event(n);
                        if (_events == null)
                            _events = new List<Event>();
                        _events.Add(e);
                    }
                }

        }
        public string toString(string space)
        {
            string ret = (space + "<widgetType name='" + _name + "' id='" + _id + "' isContainer='" + _isContainer + "'>\n");
            foreach (Property p in _properties)
                ret += (space + "\t" + p.toString(space + " "));
            foreach (Event e in _events)
                ret += (space + "\t" + e.toString(0, space + " "));
            if(containsWidgets!=null)
                ret += (space + "\t" + containsWidgets.toString(space + " ", true));
            if(_cardinality!=null && _cardinality.Count>0)
                foreach (String ca in _cardinality)
                {
                    ret += (space + "\t" + ca + "\n");
                }
            ret += (space + "</widgetType>\n");
            return ret;
        }
        public string toString(string space, bool wt)
        {
            string ret = (space + "<containsWidget name='" + _name + "' id='" + _id + "' isContainer='" + _isContainer + "'>\n");
            foreach (Property p in _properties)
                ret += (space + "\t" + p.toString(space + " "));
            foreach (Event e in _events)
                ret += (space + "\t" + e.toString(0, space + " "));
            if (containsWidgets != null)
                ret += (space + "\t" + containsWidgets.toString(space + " "));
            if (_cardinality != null && _cardinality.Count > 0)
                foreach (String ca in _cardinality)
                {
                    ret += (space + "\t" + ca + "\n");
                }

            ret += (space + "</containsWidget>\n");
            return ret;
        }

    }
    public class Behaviour
    {

        private XmlNode _node;

        private string xmlNode = "";

        public string XmlNode
        {
            get { return xmlNode; }
            set { xmlNode = value; }
        }

        public XmlNode Node
        {
            get { return _node; }
            set { _node = value; }
        }
        private int _id;

        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public Behaviour(XmlNode node)
        {

            xmlNode = node.OuterXml;
        }
        public string toString(string space)
        {
            return space + "\t" + xmlNode + "\n";

        }

    }
 
    

}
